import java.awt.Color;
import java.util.ArrayList;
import java.util.Vector;

import uchicago.src.sim.gui.Drawable;
import uchicago.src.sim.gui.SimGraphics;
import uchicago.src.sim.space.Multi2DGrid;
import uchicago.src.sim.space.Multi2DHexagonalGrid;
import uchicago.src.sim.space.Object2DTorus;
import uchicago.src.sim.util.Random;


public class BombeiroAgent  implements Drawable {

	
		private int x, y, id, objectiveX, objectiveY,teamid;
		public int stepCount;
		private Color color;
		private boolean walking;
		private Multi2DGrid space;
		
		public static final int NORMAL=0;
		public static final int BARREIRA=1;
		public static final int OVER=-1;
		
		public int estado,step;
		public int linepos,barreiraminx,barreiramaxx,barreiraminy,barreiramaxy;
		
		private ArrayList<Cell> barreira;
		public boolean still;
		public int estadoVento;
		public int foco;
					

		public BombeiroAgent(int id, Multi2DGrid space,int teamid, int f){
			this.color = Color.BLUE;
			this.space = space;
			this.id=id;
			this.walking = true;
			this.stepCount = 0;
			this.teamid = teamid;
			step=0;
			still=false;
			foco = f;
			
		}
		
		public BombeiroAgent(int id,int x, int y, Multi2DGrid space,int teamid, int f){
			this.color = Color.BLUE;
			this.space = space;
			this.id=id;
			this.x = x;
			this.y = y;
			this.stepCount = 0;
			this.teamid = teamid;
			step=0;
			still=false;
			foco = f;
			
		}
		
		public void setEstado(int e)
		{
			estado=e;
		}

		public void draw(SimGraphics g) {
			g.drawFastCircle(color);
		}


		public void walk() {
			System.out.println("Bomber E"+teamid+"B"+id+" a andar para x:"+objectiveX+" y:"+objectiveY);

			space.removeObjectAt(this.x, this.y,this);

			int xi=0,yi=0;
			if (Math.abs(objectiveX-x)>Math.abs(objectiveY-y)){
				if (x<objectiveX) xi= 1;
				else xi = -1;

			}
			else {
				if (y<objectiveY) yi = 1;
				else yi= -1;

			}

			x+= xi;
			y+=yi;

			space.putObjectAt(this.x, this.y, this);

			if (inFireRange())
			{
				System.out.println("Bomber E"+teamid+"B"+id+" tou em fire range");//+(this.x+xi)+" "+(this.y+yi));
				if (estado==BARREIRA)
				{	
					if(step==0)
					{
						Cell c = FireFighterSimulatorModel.getCellFromSpace(objectiveX, objectiveY, space);
						c.ardeuTotal = true;
						c.color = Color.black;
						c.extinct = true;
						barreira.remove(c);
						System.out.println("Bomber E"+teamid+"B"+id+" Tou na barreira step0, vou por a arder "+objectiveX+" "+objectiveY);
						newObjective();
					}
					else
					{
						if (step==1)
						{
							System.out.println("Bomber E"+teamid+"B"+id+" Tou na barreira step1, vou para step2");
							step=2;
							newObjective();
							//	step=2;
						}
						else
						{
							if (step==2)
							{
								step=3;
								System.out.println("Bomber E"+teamid+"B"+id+" Tou na barreira step2, vou para step3");
								newObjective();
							}
						}
					}
				}

				else
					walking=false;
			}
		}

		public boolean apagaFogo(){
			
			
			System.out.println("Bomber E"+teamid+"B"+id+" apagando x:"+objectiveX+" y:"+objectiveY);
			Cell c = FireFighterSimulatorModel.getCellFromSpace(objectiveX, objectiveY, space);
			if(c.arder()) 
			{
				if(!c.apagaFogo()){
					//stepCount = 0;
					FireFighterSimulatorModel.removeCellArder(c);
					System.out.println("Bomber E"+teamid+"B"+id+" YEAH, extingui x:"+objectiveX+" y:"+objectiveY);
					if(estado==BARREIRA)
						barreira.remove(c);

					newObjective();

					return true;
				}
				else System.out.println("Bomber E"+teamid+"B"+id+" lets try again on x:"+objectiveX+" y:"+objectiveY);
			}
			else 
				if(!newObjective())
					return apagaFogo();
			
			
			return false;
		}
		
		public boolean barreiraDecision()
		{
			switch(step)
			{
			case 0:
				System.out.println("step0");
				int cc = 0; 
				boolean found=false;

				while(!found && cc<barreira.size()) // pouco eficiente, rmeover
				{
					Cell cell = barreira.get(cc);
					if (!cell.drowning)
					{
						objectiveX=cell.getX();
						objectiveY=cell.getY();
						cell.drowning=true;
						found=true;

					}
					else cc++;
				}

				if(!found)
				{
					step=1;
					System.out.println("Bomber E"+teamid+"B"+id+" a barreira ta ja acabada, vou para step 1");
					return newObjective();
				}

				break;

			case 1:
				System.out.println("step1");

				switch(estadoVento)
				{

				case FireFighterSimulatorModel.NORTE:

					if (id<4)
						objectiveX = barreiraminx;
					else
						objectiveX = barreiramaxx;

					objectiveY = linepos;

					break;

				case FireFighterSimulatorModel.SUL:

					if (id<4)
						objectiveX = barreiraminx;
					else
						objectiveX = barreiramaxx;

					objectiveY = linepos;
					System.out.println("CHECK2->"+objectiveY);

					break;

				case FireFighterSimulatorModel.OESTE:

					if (id<4)
						objectiveY = barreiraminy;
					else
						objectiveY = barreiramaxy;

					objectiveX = linepos;

					break;

				case FireFighterSimulatorModel.ESTE:

					if (id<4)
						objectiveY = barreiraminy;
					else
						objectiveY = barreiramaxy;

					objectiveX = linepos;

					break;
				}

				break;

			case 2:
				System.out.println("step2");
				ArrayList<Integer> newpos = nextStep(step, id);
				objectiveX = newpos.get(0);
				objectiveY = newpos.get(1);
				break;

			case 3:

				System.out.println("step3");
				estado=NORMAL;
				ArrayList<Integer> newposi = nextStep(step, id);
				objectiveX = newposi.get(0);
				objectiveY = newposi.get(1);

				break;
			}

			if (step==3 && inFireRange())
				walking=false;
			else
				walking=true;
			return walking;

		}

		public boolean stepBack(){
			boolean stepBack = false;
			int sx=0,sy=0;
			
			
			if(checkBounds(x-1,y)&&(FireFighterSimulatorModel.getCellFromSpace(x-1, y, space)).arder()){
				
				sx = 1;
				stepBack = true;
			}
			else if(checkBounds(x,y+1)&&(FireFighterSimulatorModel.getCellFromSpace(x, y+1, space)).arder()){
				sy=  -1;
				stepBack = true;
			}
			else if(checkBounds(x+1,y)&&(FireFighterSimulatorModel.getCellFromSpace(x+1, y, space)).arder()){
				sx = -1;
				stepBack = true;
			}
			else if(checkBounds(x,y-1)&&(FireFighterSimulatorModel.getCellFromSpace(x, y-1, space)).arder()){
				sy = 1;
				stepBack = true;
			}
			
			if(stepBack){
				if(stepCount == 4) { still=true; return false; }//return false;
				else stepCount++;
				System.out.println("Bomber E"+teamid+"B"+id+", andei pra tras! myx:"+x+" myy:"+y);
				space.removeObjectAt(this.x, this.y,this);
				x+= sx;
				y+= sy;
				space.putObjectAt(this.x, this.y, this);
				FireFighterSimulatorModel.getCellFromSpace(objectiveX, objectiveY, space).drowning=false;
				
				
				objectiveX=x-sx;
				objectiveY=y-sy;
				FireFighterSimulatorModel.getCellFromSpace(objectiveX, objectiveY, space).drowning=true;
				walking=false;
			
			}
			return stepBack;
		}
		
		
		public boolean newObjective() {

			System.out.println("Bomber E"+teamid+"B"+id+" s"+estado+" calculating new objective from x:"+objectiveX+" y:"+objectiveY);
			FireFighterSimulatorModel.getCellFromSpace(objectiveX, objectiveY, space).drowning=false;
			Cell c;
			boolean found=false;


			if (estado==BARREIRA)
			{
				System.out.print("\nBomber E"+teamid+"B"+id+" na barreira ");
				return barreiraDecision();

			}


			else
			{
				found = false;
				for(int radius = 1; radius < 10 && !found; radius++){ //raio
					for(int yy = y+radius; yy >= y-radius && !found;yy--){

						if (yy>=0&&yy<100){
							//	System.out.println("D x:"+(x-radius) + " y:"+yy);
							if ((x-radius)>=0)
							{
								c=FireFighterSimulatorModel.getCellFromSpace(x-radius, yy, space);
								if(c.arder && !c.drowning){
									objectiveX = x - radius;
									objectiveY = yy;
									c.drowning=true;
									found=true;
									
								}
							}


							if ((x+radius)<100 && !found)
							{
								c=FireFighterSimulatorModel.getCellFromSpace(x+radius, yy, space);
								if(c.arder && !c.drowning){
									objectiveX = x + radius;
									objectiveY = yy;
									c.drowning=true;
									found=true;
								}
							}

							if(!found && (yy == y+radius || yy == y-radius)){
								for(int xx = x-radius+1; xx <= x+radius-1 && !found;xx++){

									if(xx>=0&&xx<100)
									{

										c=FireFighterSimulatorModel.getCellFromSpace(xx, yy, space);
										if(c.arder && !c.drowning){
											objectiveX = xx;
											objectiveY = yy;
											c.drowning=true;
											found=true;
										}
									}
								}
							}
						}
					}
				}


				if(!found)
					if(pesquisaEquipa()) 
						found = true;
				
				if(!found)
					if(FireFighterSimulatorModel.getNearestCellFromFoco(x, y, foco) != null){
						ArrayList<Integer> pos = FireFighterSimulatorModel.getNearestCellFromFoco(x, y, foco);
						objectiveX = pos.get(0);
						objectiveY = pos.get(1);
						System.out.println("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
						found = true;
					}


				if(!found)
				{	
					estado = OVER;
					walking =true;
					System.out.println(" to FINAL");
					return true;
				}
			
				
			System.out.print(" to x:"+objectiveX + " y:"+objectiveY);


			if (inFireRange())
			{
				walking =false;
				System.out.println(" in fire range");
			}
			else
			{
				walking=true;
				System.out.println(" not in fire range");
			}


			return walking;
			}}
		
		public boolean pesquisaEquipa(){
			ArrayList<BombeiroAgent> bombs = FireFighterSimulatorModel.getTeams().get(teamid).getBombeiros();
			for(int i = 0; i < bombs.size();i++){
				ArrayList<Integer> pos = bombs.get(i).procuraFogo();
				if(pos.size() == 2){
					objectiveX = pos.get(0);
					objectiveY = pos.get(1);
					System.out.println("Fui buscar o objectivo x:"+objectiveX+" y:"+objectiveY+" ao bomber:"+bombs.get(i).getId());
					return true;
				}
			}
			for(Team t:FireFighterSimulatorModel.getTeams())
				if(t.getId() != teamid){
					bombs = t.getBombeiros();
					for(int i = 0; i < bombs.size();i++){
						ArrayList<Integer> pos = bombs.get(i).procuraFogo();
						if(pos.size() == 2){
							objectiveX = pos.get(0);
							objectiveY = pos.get(1);
							System.out.println("Fui buscar o objectivo x:"+objectiveX+" y:"+objectiveY+" ao bomber:"+bombs.get(i).getId());
							return true;
						}
					}
				}
			return false;
		}
		
		public ArrayList<Integer> procuraFogo(){
			ArrayList<Integer> pos = new ArrayList<Integer>();
			Cell c;
			for(int radius = 1; radius < 10; radius++){ //raio
				for(int yy = y+radius; yy >= y-radius ;yy--){

					if (yy>=0&&yy<100){
						if ((x-radius)>=0)
						{
							c=FireFighterSimulatorModel.getCellFromSpace(x-radius, yy, space);
							if(c.arder && !c.drowning){
								pos.add(x - radius);
								pos.add(yy);
								c.drowning=true;
								return pos;
							}
						}


						if ((x+radius)<100)
						{
							c=FireFighterSimulatorModel.getCellFromSpace(x+radius, yy, space);
							if(c.arder && !c.drowning){
								pos.add(x + radius);
								pos.add(yy);
								c.drowning=true;
								return pos;
							}
						}

						if(yy == y+radius || yy == y-radius){
							for(int xx = x-radius+1; xx <= x+radius-1;xx++){

								if(xx>=0&&xx<100)
								{

									c=FireFighterSimulatorModel.getCellFromSpace(xx, yy, space);
									if(c.arder && !c.drowning){
										pos.add(xx);
										pos.add(yy);
										c.drowning=true;
										return pos;
									}
								}
							}
						}
					}
				}
			}
			return pos;
		}
		
		public void setPosition(int xx, int yy, ArrayList<Object> cellL){
			this.x = xx;
			this.y = yy;
			
			space.putObjectAt(x,y, this);
			cellL.add(this);
		}
		
		public int getObjectiveX() {
			return objectiveX;
		}

		public int getObjectiveY() {
			return objectiveY;
		}
		
		public void setObjectiveX(int x)
		{ 
			this.objectiveX=x;
		}
		
		public void setObjectiveY(int y)
		{ 
			this.objectiveY=y;
		}
		
		public int getX() {
			return x;
		}

		public int getY() {
			return y;
		}
		
		public void setX(int x)
		{ 
			this.x=x;
		}
		
		public void setY(int y)
		{ 
			this.y=y;
		}

		public Color getColor() {
			return color;
		}
		
		public int getId()
		{
			return id;
		}
	
		public boolean walking(){
			return walking;
		}

		public boolean getWalking(){
			return walking;
		}
		
		public void setWalking(boolean boll){
			walking = boll;
		}
	
		public static boolean checkBounds(int x,int y)
		{
			if (x<=0) return false;
			if (x>99) return false;
			if (y<=0) return false;
			if (y>99) return false;
			return true;
		}
		
		public void setLine(ArrayList<Cell> line,int e_vento,int f,int barreiramin,int barreiramax,int linep)
		{
			estadoVento = e_vento;
			barreira=line;
			foco=f;
			linepos=linep;
			if(estadoVento==FireFighterSimulatorModel.NORTE || estadoVento==FireFighterSimulatorModel.SUL)
			{
				barreiraminx=barreiramin;
				barreiramaxx=barreiramax;
			}
			else
			{
				barreiraminy=barreiramin;
				barreiramaxy=barreiramax;
			}
		}
		
		public boolean inFireRange()
		{
			if(Math.abs(x-objectiveX)<=2 && Math.abs(y-objectiveY)<=2)
				return true;
			else
				return false;
		
		}
		
		public ArrayList<Integer> nextStep(int step,int id){
			{
				ArrayList<Integer> perm = FireFighterSimulatorModel.getPerimeter(foco);
			//	System.out.println("STEPPING 2 foco->"+b.foco);
				ArrayList<Integer> ret = new ArrayList<Integer>();
				int objx=-1,objy=-1;
				int espaco_entre_bombeiros;
				
				if (step==2)
				{
					
					switch(estadoVento)
					{
					
					case FireFighterSimulatorModel.NORTE:
					
					espaco_entre_bombeiros = ((perm.get(1)-perm.get(3))/8);	
					if(id<4)
					{
						objx=barreiraminx;
						objy=perm.get(1);
					}
					else
					{
						objx=barreiramaxx;
						objy=perm.get(1);
					}
					
					break;
					
					case FireFighterSimulatorModel.SUL:
						
						espaco_entre_bombeiros = ((perm.get(1)-perm.get(3))/8);	
						if(id<4)
						{
							objx=barreiraminx;
							//objy=linepos-(id*espaco_entre_bombeiros);
							objy=perm.get(3);//-(id*espaco_entre_bombeiros);
						}
						else
						{
							objx=barreiramaxx;
							//objy=linepos-((id-4)*espaco_entre_bombeiros);
							objy=perm.get(3);//-(id*espaco_entre_bombeiros);
						}

						break;

					
					
				case FireFighterSimulatorModel.OESTE:
					
					espaco_entre_bombeiros = ((perm.get(0)-perm.get(2))/8);	
					if(id<4)
					{
						objx=perm.get(0);
						objy=barreiraminy;
						
					}
					else
					{
						//objx=linepos+((id-4)*espaco_entre_bombeiros);
						objx=perm.get(0);
						objy=barreiramaxy;
					}

					break;

				
					
					
				case FireFighterSimulatorModel.ESTE:
					
					espaco_entre_bombeiros = ((perm.get(0)-perm.get(2))/8);	
					if(id<4)
					{
						//objx=linepos-(id*espaco_entre_bombeiros);
						objx=perm.get(2);
						objy=barreiraminy;
						
					}
					else
					{
						//objx=linepos-((id-4)*espaco_entre_bombeiros);
						objx=perm.get(2);
						objy=barreiramaxy;
					}

					break;

				}


					while(objx>99) objx--;
					while(objx<0) objx++;
					while(objy>99) objy--;

					ret.add(objx);
					ret.add(objy);
				}


				if (step==3)
				{
					ret= FireFighterSimulatorModel.getNearestCellFromFoco(x,y,foco);

				}

				return ret;

			}
		}
			
			
}
